import React from "react";
//react的状态不可变!,不能直接修改，要采取重新赋值的方式

/**
 * setState处在同步的逻辑中，是异步函数：异步更新状态，更新真实dom
 * 此时同一个同步函数中的所有setState会被合并在一起然后再统一调用，即相当于只调用了一次setState
 * 因为此时setState是异步的，则在setState之后直接获取state状态的值是获取不到最新的状态值的：
 * setState第二个参数接收回调函数（在setState更新完状态后调用），在该函数内可以获得setState更新后的值
 * 
 * 经典题：
 *  class HelloClass extends React.Component {
      state = {
        count:0
      };
      change = () => {
        this.setState({ count: this.state.count+1});
         console.log(this.state.count); //0

        this.setState({ count: this.state.count+1});
         console.log(this.state.count); //0

        this.setState({ count: this.state.count+1});

        //因为此时setState是异步的，不会阻塞后面代码的执行
        //则每一个setState执行的时候拿到的count都是老状态0
        //change函数执行后count是1而不是3
      };
      render() {
        return (
            <div>
              当前count为：{this.state.count} //点击修改状态按钮后显示的是1而不是3
              <button onClick={this.change}>修改状态</button>
            </div>
        );
      }
    }
 */

/**
 * setState处在异步的逻辑（如定时器）中，是同步函数，同步更新状态，同步更新真实dom
 * 此时同一个异步逻辑中所有的setState都会单独调用立即执行，不会被合并在一起统一调用，即相当于执行多次setState
 * 
 * 经典题：
 *  class HelloClass extends React.Component {
      state = {
        count:0
      };
      change = () => {
        setTimeout(()=>{
          this.setState({ count: this.state.count+1});
          console.log(this.state.count); //1

          this.setState({ count: this.state.count+1});
          console.log(this.state.count); //2

          this.setState({ count: this.state.count+1});
          console.log(this.state.count); //3

          //因为此时setState是同步的，会阻塞后面代码的执行
          //则每一个setState执行的时候拿到的count都是老状态0
          //change函数执行后count是3
        },0)
      };
      render() {
        return (
            <div>
              当前count为：{this.state.count} //点击修改状态按钮后显示的是3
              <button onClick={this.change}>修改状态</button>
            </div>
        );
      }
    }
*/

class HelloClass extends React.Component {
    //1.定义组件状态
    state = {
        //在这里可以定义各种属性，全都是当前组件的状态
        name: "cbj",
        count: 0,
        list: ["1", 2, 5],
        preson: {
            age: 18,
            name: "cbj",
        },
    };
    //事件回调函数
    change = () => {
        //3.修改状态:简单类型修改

        this.setState(
            {
                name: "陈",
                count: this.state.count + 1,
                list: [...this.state.list, 4],
                preson: {
                    ...this.state.preson,
                    //覆盖原来的属性就可以达到修改的目的
                    name: "chenchen",
                },
            },
            //setState第二个参数接收回调函数（在setState更新完状态后调用），在该函数内可以获得setState更新后的值
            () => {
                //状态和真实DOM已经更新完了
                console.log(this.state.name); //陈
            }
        );
        //这里打印的是老状态cbj，并不是修改后的‘陈’，说明此时setState是异步函数
        //setState是异步函数时，想要获取到setState更新后的值，可以通过上面的方法在setState第二个参数中获取
        console.log(this.state.name); //cbj
        //不使用setState的第二个参数，也可以使用async 和 await
    };
    //删除数组状态list内的值
    delete = () => {
        this.setState({
            list: this.state.list.filter((item) => item !== 4),
        });
    };
    render() {
        // 2.使用状态
        return (
            <>
                <div>
                    当前name为：{this.state.name}
                    <button onClick={this.change}>修改name状态</button>
                    <button onClick={this.delete}>删除list内的4</button>
                </div>
                <div>person里的name为：{this.state.preson.name}</div>
                <ul>
                    {this.state.list.map((item, index) => (
                        <li key={index}>{item}</li>
                    ))}
                </ul>
            </>
        );
    }
}
function App() {
    return (
        <div className='App'>
            {/* 渲染HelloClass类组件 */}
            <HelloClass></HelloClass>
        </div>
    );
}

export default App;

/**
 * 没有state的组件叫无状态组件。
 * 因为状态会带来管理的复杂性，我们尽量少写有状态的组件（推荐通过属性props控制），这样会降低代码维护的难度，一定程度上增强组件的可复用性
 */
